﻿
package extremefx.modules.seaDragon {
	import extremefx.geom.XPoint;
	import extremefx.geom.Size;
	
	import flash.geom.Rectangle;		

	/**
	 * @author Marcelo Volmaro
	 */
	public class TileSource {
		protected var _aspectRatio:Number;
		public var width:Number;
		public var height:Number;
		
		public var minLevel:uint;
		public var maxLevel:uint;
		public var tileSize:uint;
		public var tileOverlap:uint;

		public function TileSource(pSize:Size, pTileSize:uint = 0, pTileOverlay:uint = 0, pMinLevel:uint = 0, pMaxLevel:uint = 0) {
			_aspectRatio = pSize.width / pSize.height;
			width = pSize.width;
			height = pSize.height;
			minLevel = pMinLevel || 0;
			maxLevel = pMaxLevel || Math.ceil(Math.log(Math.max(pSize.width, pSize.height)) / Math.log(2));
			
			tileSize = pTileSize || 0;
			tileOverlap = pTileOverlay || 0;
		}
		
		public function getLevelScale(pLevel:uint):Number {
			return  1 / (1 << (maxLevel - pLevel));
		}
		
		public function getNumTiles(pLevel:uint):Size {
			var s:Number = getLevelScale(pLevel);
			return new Size(Math.ceil(s * width / tileSize), Math.ceil(s * height / tileSize));
		}
		
		public function getPixelRatio(pLevel:uint):XPoint {
			var imageSizeScaled:XPoint = (new XPoint(width, height)).times(getLevelScale(pLevel));
			return new XPoint(1 / imageSizeScaled.x, 1 / imageSizeScaled.y);
		}
		
		public function getTileAtPoint(pLevel:uint, pPoint:XPoint):XPoint {
			var pixel:XPoint = pPoint.times(width).times(getLevelScale(pLevel));
			return new XPoint(Math.floor(pixel.x / tileSize),  Math.floor(pixel.y / tileSize));
		}
		
		public function getTileBounds(pLevel:uint, pX:uint, pY:uint):Rectangle {
			var dimensionsScaled:XPoint = (new XPoint(width, height)).times(getLevelScale(pLevel));
			
			var px:Number = (pX === 0) ? 0 : tileSize * pX - tileOverlap;
			var py:Number = (pY === 0) ? 0 : tileSize * pY - tileOverlap;
			var sx:Number = tileSize + (pX === 0 ? 1 : 2) * tileOverlap;
			var sy:Number = tileSize + (pY === 0 ? 1 : 2) * tileOverlap;
			sx = Math.min(sx, dimensionsScaled.x - px);
			sy = Math.min(sy, dimensionsScaled.y - py);
			var scale:Number = 1.0 / dimensionsScaled.x;
			
			return new Rectangle(px * scale, py * scale, sx * scale, sy * scale);
		}
		
		public function getTileUrl(pLevel:uint, pX:uint, pY:uint):String {
			throw new Error("Method not implemented.");
		}
		
		public function tileExists(pLevel:uint, pX:uint, pY:uint):Boolean {
			var numTiles:Size = getNumTiles(pLevel);
			return 	pLevel >= minLevel && 
					pLevel <= maxLevel && 
					pX >= 0 && 
					pY >= 0 && 
					pX < numTiles.width && 
					pY < numTiles.height;
		}
		
	}
}
